package com.g2room.eth;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.web3j.crypto.*;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.response.EthGetBalance;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Transfer;
import org.web3j.utils.Convert;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;

public class SimpleWei3J {
    //以太坊节点RPC地址
    private static final String RPC_URL = "http://192.168.0.159:8545";
    //使用http服务连接节点构建web3j对象
    private static final Web3j web3 = Web3j.build(new HttpService(RPC_URL));

    public static void main(String[] args) {
        Web3j web3 = Web3j.build(new HttpService(RPC_URL));  // defaults to http://localhost:8545/
        Web3ClientVersion web3ClientVersion = null;
        try {
            // 发送同步请求
            web3ClientVersion = web3.web3ClientVersion().send();
            web3ClientVersion = web3.web3ClientVersion().sendAsync().get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String clientVersion = web3ClientVersion.getWeb3ClientVersion();
//
//        String add = "0x3AaC3a66127BCA1f618624388FeAc36ADC9a8Ef0";
//        try {
////            System.out.println(getETHBalance(add));
//            System.out.println(createWallet(add, "D:\\user\\temp\\1\\"));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 创建钱包
     *
     * @param password 生成的keyStore密码
     * @param outPath  生成的keyStore文件存放路径
     */
    public static String createWallet(String password, String outPath) throws Exception {
        //创建新钱包KeyStore文件
        String fileName = WalletUtils.generateFullNewWalletFile(password, new File(outPath));
        //通过KeyStore文件加载钱包
        Credentials credentials = WalletUtils.loadCredentials(password, outPath + fileName);
        //通过钱包获取私钥
        BigInteger privateKey = credentials.getEcKeyPair().getPrivateKey();
        return privateKey.toString(16);
    }

    /**
     * 加载钱包对象(Credentials)四种方式
     * 1.通过私钥
     * 2.通过密钥对
     * 3.通过密码+keyStore路径
     * 4.通过密码+keyStore字符串
     */
    public static Credentials loadCredentials(String privateKey) {
        return Credentials.create(privateKey);
    }

    public static Credentials loadCredentials(ECKeyPair keyPair) {
        return Credentials.create(keyPair);
    }

    public static Credentials loadCredentials(String password, String keyStoreUrl) throws IOException, CipherException {
        return WalletUtils.loadCredentials(password, keyStoreUrl);
    }

    public static Credentials loadCredentialsByString(String password, String keyStoreJson) throws IOException, CipherException {
        WalletFile walletFile = new ObjectMapper().readValue(keyStoreJson, WalletFile.class);
        return Credentials.create(Wallet.decrypt(password, walletFile));
    }

    /**
     * 查询以太币余额
     *
     * @Param address 需要查询的钱包地址
     */
    public static String getETHBalance(String address) throws IOException {
        Request<?, EthGetBalance> request = web3.ethGetBalance(address, DefaultBlockParameter.valueOf("LATEST"));
        EthGetBalance balance = request.send();
        BigDecimal banlance = new BigDecimal(balance.getBalance());
        return banlance.divide(new BigDecimal("10").pow(18)).toPlainString();
    }

    /**
     * ETH单笔转账
     *
     * @param address     to地址
     * @param count       to数量
     * @param credentials from钱包对象
     */
    public static TransactionReceipt transferETH(String address, BigDecimal count, Credentials credentials) throws Exception {
        return Transfer.sendFunds(web3, credentials, address, count, Convert.Unit.ETHER).send();
    }

    /**
     * 获取当前nonce
     *
     * @param address 需要查询的钱包地址
     */
    public static String getNonce(String address) throws IOException {
        return web3.ethGetTransactionCount(address, DefaultBlockParameterName.LATEST).send().getTransactionCount().toString();
    }
}
